package com.epfly.promo.activity.impl;


import com.epfly.base.id.SnowflakeIdService;
import com.epfly.base.util.DateUtil;
import com.epfly.iface.promo.activity.ActivityOrderService;
import com.epfly.iface.promo.activity.enums.ActivityRuleDinnerTypeEnum;
import com.epfly.iface.promo.activity.vo.GetDiscountAndLockAmountRequest;
import com.epfly.iface.promo.activity.vo.RollbackDiscountAmountRequest;
import com.epfly.iface.promo.activity.vo.UnlockDiscountAmountRequest;
import com.epfly.iface.promo.activity.vo.UseDiscountAmountRequest;
import com.epfly.promo.activity.dao.UserActivityDayStatisticsMapper;
import com.epfly.promo.activity.dao.UserActivityDinnerStatisticsMapper;
import com.epfly.promo.activity.entity.UserActivityDayStatisticsEntity;
import com.epfly.promo.activity.entity.UserActivityDinnerStatisticsEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Objects;

@Service
public class ActivityOrderServiceImpl implements ActivityOrderService {


    @Resource
    private UserActivityDinnerStatisticsMapper userActivityDinnerStatisticsMapper;

    @Resource
    private UserActivityDayStatisticsMapper userActivityDayStatisticsMapper;

    @Resource
    private SnowflakeIdService snowflakeIdService;


    /**
     * 用户级加锁, 必须和"创建订单"在同一个事务
     * 即：订单创建成功的同时，锁定已享受优惠。
     */
    @Transactional
    @Override
    public void getAndLockDiscountAmount(GetDiscountAndLockAmountRequest request) {

        // 用户ID
        String userId = request.getUserId();
        // 将参与的活动
        Long activityId = request.getActivityId();
        // 将获得的优惠金额
        BigDecimal discountAmount = request.getDiscountAmount();

        if (discountAmount.compareTo(BigDecimal.ZERO) > 0) {
            Long orderTime = request.getOrderTime();

            // TODO 根据订单时间计算餐别
            byte dinnerType = ActivityRuleDinnerTypeEnum.NIGHT.getKey();

            UserActivityDinnerStatisticsEntity dinnerStatisticEntity = userActivityDinnerStatisticsMapper.findByUserIdActivityIdAndDinnerType(userId, activityId, dinnerType);
            if (Objects.isNull(dinnerStatisticEntity)) {
                long id = snowflakeIdService.nextId();
                dinnerStatisticEntity = new UserActivityDinnerStatisticsEntity();
                dinnerStatisticEntity.setId(id);
                dinnerStatisticEntity.setUserId(userId);
                dinnerStatisticEntity.setActivityId(activityId);
                dinnerStatisticEntity.setDinnerType(dinnerType);
                dinnerStatisticEntity.setTotalAmount(BigDecimal.ZERO);
                dinnerStatisticEntity.setTotalCount(0);
                dinnerStatisticEntity.setOnWayAmount(discountAmount);
                dinnerStatisticEntity.setOnWayCount(1);
                userActivityDinnerStatisticsMapper.insertSelective(dinnerStatisticEntity);
            } else {
                userActivityDinnerStatisticsMapper.increaseOnWayAmountAndOnWayCount(userId, activityId, dinnerType, discountAmount, 1);
            }

            // 日统计
            Integer day = DateUtil.getDateByProvidedTime(orderTime);
            UserActivityDayStatisticsEntity dayStatisticsEntity = userActivityDayStatisticsMapper.findByUserIdAndActivityIdAndDay(userId, activityId, day);
            if (Objects.isNull(dayStatisticsEntity)) {
                long id = snowflakeIdService.nextId();
                dayStatisticsEntity = new UserActivityDayStatisticsEntity();
                dayStatisticsEntity.setId(id);
                dayStatisticsEntity.setUserId(userId);
                dayStatisticsEntity.setActivityId(activityId);
                dayStatisticsEntity.setDay(day);
                dayStatisticsEntity.setTotalAmount(BigDecimal.ZERO);
                dayStatisticsEntity.setTotalCount(0);
                dayStatisticsEntity.setOnWayAmount(discountAmount);
                dayStatisticsEntity.setOnWayCount(1);
                userActivityDayStatisticsMapper.insertSelective(dayStatisticsEntity);
            } else {
                userActivityDayStatisticsMapper.increaseOnWayAmountAndOnWayCount(userId, activityId, day, discountAmount, 1);
            }
        }
    }

    /**
     * 场景：
     * 1.支付失败
     * 2.待支持-->已取消
     */
    @Transactional
    @Override
    public void unlockDiscountAmount(UnlockDiscountAmountRequest request) {

        // TODO 根据订单时间拿到餐别
        Byte dinnerType = ActivityRuleDinnerTypeEnum.NIGHT.getKey();

        Integer day = DateUtil.getDateByProvidedTime(request.getOrderTime());

        userActivityDinnerStatisticsMapper.decreaseOnWayAmountAndOnWayCount(request.getUserId(), request.getActivityId(), dinnerType, request.getDiscountAmount(), 1);

        userActivityDayStatisticsMapper.decreaseOnWayAmountAndOnWayCount(request.getUserId(), request.getActivityId(), day, request.getDiscountAmount(), 1);
    }

    /**
     * 待支付->支付成功的回调函数(callback)
     */
    @Transactional
    @Override
    public void useDiscountAmount(UseDiscountAmountRequest request) {

        // TODO 根据订单时间拿到餐别
        Byte dinnerType = ActivityRuleDinnerTypeEnum.NIGHT.getKey();

        Integer day = DateUtil.getDateByProvidedTime(request.getOrderTime());

        userActivityDinnerStatisticsMapper.consumeOnWay(request.getUserId(), request.getActivityId(), dinnerType, request.getDiscountAmount(), 1);
        userActivityDayStatisticsMapper.consumeOnWay(request.getUserId(), request.getActivityId(), day, request.getDiscountAmount(), 1);
    }

    /**
     * 已支付成功-->退单的回调函数(callback)
     */
    @Transactional
    @Override
    public void rollbackDiscountAmount(RollbackDiscountAmountRequest request) {
        // TODO 根据订单时间拿到餐别
        Byte dinnerType = ActivityRuleDinnerTypeEnum.NIGHT.getKey();

        Integer day = DateUtil.getDateByProvidedTime(request.getOrderTime());

        userActivityDinnerStatisticsMapper.rollback(request.getUserId(), request.getActivityId(), dinnerType, request.getDiscountAmount(), 1);
        userActivityDayStatisticsMapper.rollback(request.getUserId(), request.getActivityId(), day, request.getDiscountAmount(), 1);
    }


}
